#include <goldfish/head.h>
#include <goldfish/goldfishfb.h>

#define SPACE 1
#define LINEFEED 2
#define BACKSPACE 3
#define ZK8X16

#ifdef ZK8X16
extern u8 _binary_8x16_start[];
extern u8 _binary_8x16_end[];

#define ASCII2QH (ch)//2 fro 16*16
#define ASCII2WH 0//ch - 33 for 16*16
#define OFFSET 4//0 for 16*16
#define CHARSPERQU 1//94 for 16*16
#define _binary_start _binary_8x16_start
#define COLBITS 8//16 for 16*16

#else //16x16
extern u8 _binary_hzk16_start[];
extern u8 _binary_hzk16_end[];

#define ASCII2QH 2
#define ASCII2WH ((ch) - 33)
#define OFFSET 0 
#define CHARSPERQU 94
#define _binary_start _binary_hzk16_start
#define COLBITS 16

#endif

#define ROWBITS 16

#define x_num ((goldfishfb->fb.var.xres)/COLBITS)
#define y_num ((goldfishfb->fb.var.yres)/ROWBITS)

static int flag = 0;
int flag_init = 0;
int flag_dom = 0;
int flag_init_dom = 0;

u8 mask[8]={
	0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};

u8 rec[2000];
u8 rec_dom[2000];
static u8 hzkbitmap[COLBITS*ROWBITS*3];
static u8 picbitmap[COLBITS*ROWBITS*3];

struct fb_image pic = {
        .dx = 0,
        .dy = 0,
        .width = COLBITS,//goldfishfb->fb.var.xres,
        .height = 16,//goldfishfb->fb.var.yres,
        .depth = 16,
        .data = hzkbitmap,
};

struct fb_image pic_dom = {//dom pic
        .dx = 0,
        .dy = 0,
        .width = COLBITS,//goldfishfb->fb.var.xres,
        .height = 16,//goldfishfb->fb.var.yres,
        .depth = 16,
        .data = hzkbitmap,
};

void chartopic(u8* ch, u32 fgbgr);
void scrollup(u32 fgbgr);
void backpic(void *c, int dx, int dy);
void scrollup_dom(u32 fgbgr, u32 flag);

u8 * dom_bmp_start;
extern u8 _binary_24_bmp_start[];
extern unsigned int foreground_domain;
//ch[0] is qh,ch[1] is wh
void drawcharbyqh(u8* ch,int dx ,int dy,u32 fgbgr,u32 bgbgr)
{
			//u8 c = *ch;
			//u8* addr = _binary_start + (ch[0]*CHARSPERQU+ch[1])*COLBITS*ROWBITS/8+OFFSET;//_binary_hzk16_start+((ch[0])*94+ch[1])*32; for 16*16
			//static u8 hzkbitmap[COLBITS*ROWBITS*3];
			int i = 0,j = 0;
			if(flag_init == 0)
			{
				for(i = 0; i < x_num*y_num; i++)
					rec[i] = 0;
				flag_init = 1;
			}
			/*static struct fb_image pic = {
					.dx = 0,
					.dy = 0,
					.width = COLBITS,//goldfishfb->fb.var.xres,
					.height = 16,//goldfishfb->fb.var.yres,
					.depth = 16,
					.data = hzkbitmap,
				};*/
			//pic.dx +=COLBITS ;
			if(pic.dx > goldfishfb->fb.var.xres-COLBITS)
			{
				pic.dx = 0;
				pic.dy += 16;
                                if(pic.dy >= goldfishfb->fb.var.yres)
                                {
					 scrollup(fgbgr);
                                         pic.dy = goldfishfb->fb.var.yres - 16;
                                         pic.dx = 0;
                                }
			}

			if(flag == SPACE)
			{
				flag = 0;
                                pic.dx +=COLBITS;
				return;
			}
			if(flag == LINEFEED)
			{
				flag = 0;
				//pic.dy += 16;
				pic.dx = goldfishfb->fb.var.xres;
				return;
			}
                        if(flag == BACKSPACE)
                        {
                                if(pic.dx == 0 && pic.dy ==0)
				{
					 flag = 0;
					 return;
				}
				else if(pic.dx == 0 && pic.dy != 0)
			  	{
					 pic.dx = goldfishfb->fb.var.xres-COLBITS;
					 pic.dy -= 16;
				}
				else
					 pic.dx -= COLBITS;
			        //addr = _binary_start + ('\0'*CHARSPERQU+ch[1])*COLBITS*ROWBITS/8+OFFSET;
				*ch = 0;	
                        }

			if(dx >= 0 && dy >= 0 )
			{
				pic.dx = dx;
				pic.dy = dy;
			} 
		        backpic(picbitmap, pic.dx, pic.dy);

			//printk("start:%x,index:%x\n",_binary_hzk16_start,addr);
			//printk("start:%x,%s\n",_binary_24_bmp_start,_binary_24_bmp_start);
			//memset(hzkbitmap,bgbgr,16*16*3);
			//printk("*addr:%x\n",*addr);
			chartopic(ch, fgbgr);		

			rec[(pic.dy/16)*x_num + (pic.dx)/8] = *ch; 
			pic.data = hzkbitmap; 
			goldfishfb->fb.fbops->fb_imageblit(&goldfishfb->fb,&pic);
                        if(flag == BACKSPACE)
			{
				flag = 0;
				return;
			}
                        pic.dx +=COLBITS;
}


extern unsigned int foreground_domain;
void drawcharbyqh_dom(u8* ch,int dx ,int dy,u32 fgbgr,u32 bgbgr)//record dom and draw dom
{
                        int i = 0,j = 0;
                        if(flag_init_dom == 0)
                        {
                                for(i = 0; i < x_num*y_num; i++)
                                        rec_dom[i] = 0;
                                flag_init_dom = 1;
                        }

			if(pic_dom.dx > goldfishfb->fb.var.xres-COLBITS)
                        {
                                pic_dom.dx = 0;
                                pic_dom.dy += 16;
                                if(pic_dom.dy >= goldfishfb->fb.var.yres)
                                {
                                         scrollup_dom(fgbgr, bgbgr);
                                         pic_dom.dy = goldfishfb->fb.var.yres - 16;
                                         pic_dom.dx = 0;
                                }
                        }

                        if(flag_dom == SPACE)
			{
                                flag_dom = 0;
                                pic_dom.dx +=COLBITS;
                                return;
                        }
                        if(flag_dom == LINEFEED)
			{
                                flag_dom = 0;
                                //pic.dy += 16;
                                pic_dom.dx = goldfishfb->fb.var.xres;
                                return;
                        }
			if(flag_dom == BACKSPACE)
                        {
                                if(pic_dom.dx == 0 && pic_dom.dy ==0)
                                {
                                         flag_dom = 0;
                                         return;
                                }
                                else if(pic_dom.dx == 0 && pic_dom.dy != 0)
                                {
                                         pic_dom.dx = goldfishfb->fb.var.xres-COLBITS;
                                         pic_dom.dy -= 16;
                                }
                                else
                                         pic_dom.dx -= COLBITS;
                                //addr = _binary_start + ('\0'*CHARSPERQU+ch[1])*COLBITS*ROWBITS/8+OFFSET;
                                *ch = 0;
                        }

                        if(dx >= 0 && dy >= 0 )
                        {
                                pic_dom.dx = dx;
                                pic_dom.dy = dy;
                        }
			if(!bgbgr){
	                        backpic(picbitmap, pic_dom.dx, pic_dom.dy);
	
				chartopic(ch, fgbgr);
			}

                        rec_dom[(pic_dom.dy/16)*x_num + (pic_dom.dx)/8] = *ch;
                        pic_dom.data = hzkbitmap;
			if(!bgbgr)
                        	goldfishfb->fb.fbops->fb_imageblit(&goldfishfb->fb,&pic_dom);
                        if(flag_dom == BACKSPACE)
                        {
                                flag_dom = 0;
                                return;
                        }
                        pic_dom.dx +=COLBITS;
}

void chartopic(u8* ch, u32 fgbgr)
{
 	int i,j;
        j = 0;  
	u8 *addr = _binary_start + (ch[0]*CHARSPERQU+ch[1])*COLBITS*ROWBITS/8+OFFSET;

	for(i=0;i<COLBITS*ROWBITS;i++)
        {
                 if(i&&!(i%8))
                         addr++;
                 if((*addr)&mask[i%8])
                 {
                         hzkbitmap[j] = fgbgr>>16;
                         hzkbitmap[j+1] = (fgbgr>>8)&0xff;//hzkbitmap[j];
                         hzkbitmap[j+2] = fgbgr&0xff;//hzkbitmap[j];
                 }
                 else
                 {
                         memcpy(hzkbitmap + j, picbitmap + j, 3);
                 }
                 j += 3;
        }
}

void scrollup(u32 fgbgr)
{
	int i, j;
        u8 ch[2] = {'\0', ASCII2WH}; 
	for(i = 0; i < y_num - 1; i++)
	{
		for(j = 0; j < x_num; j++)
		{
			rec[i*x_num + j] = rec[i*x_num + j + x_num];
			backpic(picbitmap, j*8, i*16);
			ch[0] = rec[i*x_num+j];
			chartopic(ch, fgbgr);
			pic.dx = j*8;
			pic.dy = i*16;
			pic.data = hzkbitmap;
			goldfishfb->fb.fbops->fb_imageblit(&goldfishfb->fb,&pic);
		}
	}
        for(i = 0; i < x_num; i++)
	{
		backpic(hzkbitmap, i*8, (y_num-1)*16);
                pic.dx = i*8;
		pic.dy = (y_num-1)*16;
		goldfishfb->fb.fbops->fb_imageblit(&goldfishfb->fb,&pic);
		rec[(y_num-1)*x_num+i] = 0;
	}
}

void scrollup_dom(u32 fgbgr, u32 flag)//scroll dom
{        
	int i, j;
        u8 ch[2] = {'\0', ASCII2WH};
        for(i = 0; i < y_num - 1; i++)
        {
                for(j = 0; j < x_num; j++)
                {
                        rec_dom[i*x_num + j] = rec_dom[i*x_num + j + x_num];
                        if(!flag){
				backpic(picbitmap, j*8, i*16);
                        	ch[0] = rec_dom[i*x_num+j];
                        	chartopic(ch, fgbgr);
                        	pic_dom.dx = j*8;
	                        pic_dom.dy = i*16;
        	                pic_dom.data = hzkbitmap;
                	        goldfishfb->fb.fbops->fb_imageblit(&goldfishfb->fb,&pic_dom);
			}
                }
        }
        for(i = 0; i < x_num; i++)
        {
		if(!flag){
	                backpic(hzkbitmap, i*8, (y_num-1)*16);
        	        pic_dom.dx = i*8;
                	pic_dom.dy = (y_num-1)*16;
	                goldfishfb->fb.fbops->fb_imageblit(&goldfishfb->fb,&pic_dom);
		}
                rec_dom[(y_num-1)*x_num+i] = 0;
        }
}

void backpic(void *c, int dx, int dy)
{
        int i;
        for(i = 0; i < 16; i++)
	{
		if(foreground_domain == 1)
			memcpy(c, dom_bmp_start + 54 + dy*(goldfishfb->fb.var.xres)*3 + dx*3, 8*3);
		else
	        	memcpy(c, _binary_24_bmp_start + 54 + dy*(goldfishfb->fb.var.xres)*3 + dx*3, 8*3);
		dy++;
		c += 8*3;
	}
}

void drawchar(char ch,int dx ,int dy,u32 fgbgr,u32 bgbgr)
{
        u8 qh[2]={ASCII2QH,ASCII2WH/*(u8)ch - 33*/};
        if(ch == 32)
		flag = SPACE;
        if(ch == 0x0a)
		flag = LINEFEED;
        if(ch == '\b')
                flag = BACKSPACE;
        drawcharbyqh(qh,dx,dy,fgbgr,bgbgr);
}

void drawchar_dom(char ch,int dx ,int dy,u32 fgbgr,u32 bgbgr)//drawchar dom
{
        u8 qh[2]={ASCII2QH,ASCII2WH/*(u8)ch - 33*/};
        if(ch == 32)
                flag_dom = SPACE;
        if(ch == 0x0a)
                flag_dom = LINEFEED;
        if(ch == '\b')
                flag_dom = BACKSPACE;
        drawcharbyqh_dom(qh,dx,dy,fgbgr,bgbgr);
}

void drawstring(char* str,int dx ,int dy,u32 fgbgr,u32 bgbgr)
{
	//int len = strlen(str);
	int i = 0;
        if(!str || *str == '\0')
                return;
	if(str[i] == 0x0a)
		flag = LINEFEED;

	drawchar(str[i++],dx,dy,fgbgr,bgbgr);
	for(;str[i];i++)
	{
		if(str[i] == 32)
			flag = SPACE;
		if(str[i] == 0x0a)
			flag = LINEFEED;
                //drawchar(str[i],dx,dy,fgbgr,bgbgr);		
                drawchar(str[i],-1,0,fgbgr,bgbgr);
	}
}

void drawstring_dom(char* str,int dx ,int dy,u32 fgbgr,u32 bgbgr)//drawstring dom
{
        //int len = strlen(str);
        int i = 0;
        if(!str || *str == '\0')
                return;
        if(str[i] == 0x0a)
                flag_dom = LINEFEED;

        drawchar_dom(str[i++],dx,dy,fgbgr,bgbgr);
        for(;str[i];i++)
        {
                if(str[i] == 32)
                        flag_dom = SPACE;
                if(str[i] == 0x0a)
                        flag_dom = LINEFEED;
                //drawchar(str[i],dx,dy,fgbgr,bgbgr);           
                drawchar_dom(str[i],-1,0,fgbgr,bgbgr);
        }
}

void fresh_dom_screen(void)//fresh dom screen
{
	int dx, dy, i;
	dx = pic_dom.dx;
	dy = pic_dom.dy;
	pic_dom.dx = pic_dom.dy = 0;
	for(i = 0; i < x_num*y_num; i++)
		drawchar_dom((char)(rec_dom[i]), -1, 0, 0, 0);
	pic_dom.dx = dx;
	pic_dom.dy = dy;
}

void fresh_vmm_screen(void)//fresh dom screen
{
        int dx, dy, i;
        dx = pic.dx;
        dy = pic.dy;
        pic.dx = pic.dy = 0;
        for(i = 0; i < x_num*y_num; i++)
                drawchar((char)(rec[i]), -1, 0, 0, 0);
        pic.dx = dx;
        pic.dy = dy; 
}

void clear_dom_screen(void)//clear dom screen
{
	int i;
	pic_dom.dx = 0;
        pic_dom.dy = 0;
	for(i = 0; i < x_num*y_num; i++)
		rec_dom[i] = 0;
}
